/**
  ******************************************************************************
  * File Name          : main.c
  * Description        : Main program body
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2017 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>
#include "main.h"
#include "stm32f4xx_hal.h"
#include "delay.h"
#include "rtc.h"
#include "key.h"
#include "tim.h"
#include "i2c.h"
#include "gpio.h"
#include "usart.h"
#include "adc.h"
#include "display.h"
#include "e_ink.h"
#include "test_seq.h"
#include "short_test.h"
#include "open_test.h"
#include "battery.h"
#include "led.h"
#include "result.h"
#include "power.h"
#include "w25qxx.h"
#include "completetest.h"
#include "cap_test.h"
#include "command.h"
#include "usb_otg.h"
#include "elec_sw.h"
#include "lighting.h"
#include "dds_ad9851.h"
#include "math.h"
#include "iwdg.h"
#include "spi.h"
#include "logger.h"
#include "data_hex.h"

//RTC_DateTypeDef sdatestructure;
//RTC_TimeTypeDef stimestructure;

uint8_t 	u8Link_bat_idx=0;
uint16_t	BatVol=0;
uint8_t		Work_once_bat=0;
uint32_t	u32Iwdg=0;
uint32_t 	USCount100 = 0;
uint32_t	ADC1_AD_Value[2];
uint16_t	u16TestDelay=0;
uint16_t	u16DelayMs;
uint8_t		BeginIniStar=0;
uint8_t		u8IdxUSBCharge=0;
uint32_t	u32TimUSBChargeBat=0;
uint8_t		u8BreakDownload = 0;
uint16_t	u16TimDdPerTims = 0;
uint8_t		u8IdxDownload = 0;

//uint8_t 	StrTmp01[100];
__IO uint32_t u32uwTick;

static unsigned short MsCount10 = 0;

extern 	TIM_HandleTypeDef htim3;
extern 	TIM_HandleTypeDef htim12;
extern 	UART_HandleTypeDef huart1;
extern 	uint8_t UartRxBuffer[MAX_RX_BYTES];
extern 	uint16_t RX_ReceiveSave;
extern 	uint16_t RX_ReceiveTimeCount;
extern 	uint8_t RX_ReceiveFlag;

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);


/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

void CheckBattery(uint8_t mode)
{
    static uint8_t bat_num=0;

    if(mode)
    {
        if(u16TestDelay>TIM_20MS)
        {
            u16TestDelay=0;
            BatVol=GetBatVoltage(&UserAdc);
            if(HAL_GPIO_ReadPin(BQ24073_CHG_PG_GPIO_Port, BQ24073_CHG_PG_Pin))
            {
                if(BatVol>=4000)											//>=4.0v
                {
                    bat_num++;
                    if(bat_num>=30)											//600ms
                    {
                        bat_num=0;
                        u8Link_bat_idx=1;
                    }
                }
                else																	//<4.0v
                {
                    bat_num=0;
                    u8Link_bat_idx=0;
                }
            }
            else
            {
                bat_num=0;
                u8Link_bat_idx=0;
            }
        }
    }
    else
    {
        while(1)
        {
            delay_ms(5);
            BatVol=GetBatVoltage(&UserAdc);
            if(HAL_GPIO_ReadPin(BQ24073_CHG_PG_GPIO_Port, BQ24073_CHG_PG_Pin))
            {
                if(BatVol>=4000)											//>=4.0v
                {
                    bat_num++;
                    if(bat_num>=30)											//150ms
                    {
                        bat_num=0;
                        u8Link_bat_idx=1;
                        break;
                    }
                }
                else																	//<4.0v
                {
                    bat_num=0;
                    u8Link_bat_idx=0;
                    break;
                }
            }
            else
            {
                bat_num=0;
                u8Link_bat_idx=0;
                break;
            }
        }

        if(HAL_GPIO_ReadPin(BQ24073_NPGOOD_GPIO_Port, BQ24073_NPGOOD_Pin))
        {
            if(BatVol>3000)													//battery is larger than 3.0v at least
            {
                if(GetBatLevel(BatVol) <10)						//battery <10%
                {
                    Display_LowPower();
                    delay_ms(100);
                    PowerOff();
                    delay_ms(1000);											//remove the influenc of the remain current
                }
            }
        }
    }
}

void Disp_LowPower(void)
{
    if(HAL_GPIO_ReadPin(BQ24073_NPGOOD_GPIO_Port, BQ24073_NPGOOD_Pin))
    {
        if(BatVol>3000)													//battery is larger than 3.0v at least
        {
            if(GetBatLevel(BatVol) <10)						//battery <10%
            {
                Display_LowPower();
                PowerState = POWERMODE_OFF;
                PowerFlag = 1;
                TestBusyFlag = 0;
                return;
            }
        }
    }
}

/****************************************************************************************************************************
* @Functions:KeyProcess()
* @Description:deal the different KEY function:
MESS_KEY1LONG_DOWN:POWER OFF
MESS_KEY1_UP:begin measuring
MESS_KEY1DOUBLE_UP:change interface
* @Input:
* @Output:
* @Return:
* @Others:
* @History:
****************************************************************************************************************************/
void KeyProcess(void)
{
    static uint8_t power_off_idx=0;

    switch(KeyValue)
    {
    case MESS_KEY1LONG_DOWN:

        if(power_off_idx==1)
        {
            if(HAL_GPIO_ReadPin(BQ24073_NPGOOD_GPIO_Port, BQ24073_NPGOOD_Pin)==1)
            {
                Display_Logo();       //display poweroff logo
                PowerState = POWERMODE_OFF;
                PowerFlag = 1;
                power_off_idx=0;
                CleatKeyState();
            }
        }
        break;

    case MESS_KEY1_UP:

        if(PowerState == POWERMODE_OFF)
        {
            PowerState = POWERMODE_ON;
            PowerFlag = 1;
        }

        Work_once_bat=0;
        ConfigInitItem();
        TestRun();   												//all test is here
        CurrentPage = 0;
        CleatKeyState();

        break;
    case MESS_KEY1DOUBLE_UP:
        if(DispPage > 0)
        {
            if(DoubelDisplayFlag == 0)
            {
                Display_OpenResValue();  				//display res value
                CurrentPage++;
                if(CurrentPage >= DispPage)
                {
                    CurrentPage = 0;
                    DoubelDisplayFlag = 1;
                }
            }
            else
            {
                Display_TestResult();  				//display test result
                DoubelDisplayFlag = 0;
                CurrentPage = 0;
            }
        }
        CleatKeyState();
        break;
    }

    if(HAL_GPIO_ReadPin(BUTTON_GPIO_Port,BUTTON_Pin)== 1)
    {
        power_off_idx=1;
    }
}

void IniStar(void)
{
    if(BeginIniStar==0 && HAL_GPIO_ReadPin(BQ24073_NPGOOD_GPIO_Port, BQ24073_NPGOOD_Pin)==0)
    {
        BeginIniStar=1;
        InitTriStar();
    }
}

void InspectUSBCharge(void)
{
    if(HAL_GPIO_ReadPin(BQ24073_NPGOOD_GPIO_Port, BQ24073_NPGOOD_Pin)==0)
    {
        if(HAL_GPIO_ReadPin(BQ24073_CHG_PG_GPIO_Port, BQ24073_CHG_PG_Pin)==0)
        {
            u8IdxUSBCharge=1;
        }
        else
        {
            if(u8Link_bat_idx==1)
            {
                u8IdxUSBCharge=1;
            }
            else
            {
                u8IdxUSBCharge=0;
                u32TimUSBChargeBat=0;
            }
        }
    }
    else
    {
        u8IdxUSBCharge=0;
        u32TimUSBChargeBat=0;
    }

    if(u8IdxUSBCharge == 1 && u32TimUSBChargeBat >= TIM_3MINUTE)
    {
        u32TimUSBChargeBat=0;
        Display_Bat(112,118,0);
    }
}

/**
* @brief This function handles EXTI line[9:5] interrupts.
*/
void EXTI3_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3);
}

/**
* @brief This function handles TIM3 global interrupt.
*/
void TIM3_IRQHandler(void)										//100us
{
    /* USER CODE BEGIN TIM3_IRQn 0 */

    /* USER CODE END TIM3_IRQn 0 */
    HAL_TIM_IRQHandler(&htim3);
    /* USER CODE BEGIN TIM3_IRQn 1 */

    MsCount10++;
    USCount100++;
    u32Iwdg++;
    u16TestDelay++;
    u16DelayMs++;

    if(u32Iwdg>=5000)
    {
        u32Iwdg=0;
        HAL_IWDG_Refresh(&hiwdg);
    }

    if(RX_ReceiveSave)
    {
        RX_ReceiveTimeCount++;
        if(RX_ReceiveTimeCount > 100)
        {
            RX_ReceiveFlag = 1;
        }
    }
    KeyDet();
    if(MsCount10 >= 100)
    {
        MsCount10 = 0;
        PowerDet();
    }
    if(u8IdxUSBCharge == 1)
    {
        u32TimUSBChargeBat++;
    }

    if(u8BreakDownload == 1)
    {
        u16TimDdPerTims++;
    }
    else
    {
        u16TimDdPerTims = 0;
    }
    /* USER CODE END TIM3_IRQn 1 */
}


/**
* @brief This function handles TIM8 break interrupt and TIM12 global interrupt.
*/
void TIM8_BRK_TIM12_IRQHandler(void)					//10us
{
    /* USER CODE BEGIN TIM8_BRK_TIM12_IRQn 0 */

    /* USER CODE END TIM8_BRK_TIM12_IRQn 0 */
    HAL_TIM_IRQHandler(&htim12);
    /* USER CODE BEGIN TIM8_BRK_TIM12_IRQn 1 */
    //u32TestDelay++;
    u32uwTick++;

    /* USER CODE END TIM8_BRK_TIM12_IRQn 1 */
}

/* USER CODE END 0 */

int main(void)
{
    uint16_t i;
    u8IdxDownload = 0;
//	SCB->VTOR = 0x0800C000;   	//VECT_TAB_OFFSET=0xC000;

    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();

    MX_IWDG_Init();
    HAL_IWDG_Refresh(&hiwdg);
    PowerOn();															//enable the hardware power pin upon POWEN ON
    TLV61046_LT1931_EN();
    Delay_ms(10);
    TPS73150_EN();
    MX_TIM4_Init(PWM_PERIOD_10MS,35,35,35);													//PWM  		T=10ms
    //MX_TIM4_Init(PWM_PERIOD_1S,5000,5000,5000);
    MX_RTC_Init();
    HAL_IWDG_Refresh(&hiwdg);
    MX_ADC1_Init();													//NTC1,NTC2 and the capacity of battery
    MX_USART1_UART_Init();
    //MX_USB_OTG_FS_PCD_Init();
    MX_TIM12_Init();												//used in the CAP measurment

    HAL_IWDG_Refresh(&hiwdg);
    MX_SPI1_Init();
    W25QXX_Init();
    MX_TIM3_Init();													//normal TIM,100us per INT
    HAL_IWDG_Refresh(&hiwdg);

    W25QXX_Read(FlashMCUConfig,EEP_OFFSET_ADJ_ITEM,FLASH_CONFIG_SIZE);
    W25QXX_Read(FlashMCUReg,FLASH_APP_REG_ADR,W25QXX_SECTOR_LENGTH);
    LoggerIni();

    if(HAL_GPIO_ReadPin(BQ24073_NPGOOD_GPIO_Port, BQ24073_NPGOOD_Pin)==1)
    {
        Work_once_bat=1;
    }

    //MX_RTC_Init_DateTime(2018, 7, 7, 7, 7, 7, 7);
    //while(1);
    E_INK_Read_ID();
    E_INK_Init();         									//initialize the LCD
    HAL_IWDG_Refresh(&hiwdg);
    ConfigInitItem();												//download the configuration of the measurment when used in the first time
    HAL_IWDG_Refresh(&hiwdg);
    MuxDeinit();														//disable all the electrolic switch
    REF_1_5V_EN();												//the initial voltage of CAP-MES:1.25v      the end voltage of CAP-MES:1.875v
    Ad9851Init();														//initialize the DDS
    Ad9851SetFrequency(1000,0);							//close the DDS

    CapTest_Initialize();										//initialize the measurment of the CAP
    HAL_IWDG_Refresh(&hiwdg);
    CheckBattery(0);
    //Display_TestResult();										//initial LCD interface
    Display_Logo();
    HAL_IWDG_Refresh(&hiwdg);
    InitDownload();

    for(i=0; i<MAX_RX_BYTES; i++)
    {
        UartRxBuffer[i]=0;
    }
    RX_ReceiveSave=0;
    RX_ReceiveTimeCount=0;
    RX_ReceiveFlag=0;
    printf("iPort\r\n");
    while (1)
    {
        IniStar();
        CheckBattery(1);											//test battery
        Disp_LowPower();											//power off when battery is lower than 10%
//		InspectUSBCharge();										//display charging battery

        PowerProcess();												//manage POWER
        UartReceiveProcess();									//manage UART
        KeyProcess();													//manage KEY

        if(Work_once_bat==1)
        {   //work once on power when the pcba is supplied by battery
            Work_once_bat=0;

            ConfigInitItem();
            TestRun();   												//all test is here
            CurrentPage = 0;
            CleatKeyState();
        }

        if(u8BreakDownload == 1)
        {
            if(u16TimDdPerTims >= 30000)				//3s
            {
                u16TimDdPerTims = 0;
                u8BreakDownload = 0;
                HAL_IWDG_Refresh(&hiwdg);

                __set_FAULTMASK(1);
                NVIC_SystemReset();
            }
        }
    }
    /* USER CODE END 3 */
}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

    RCC_OscInitTypeDef RCC_OscInitStruct;
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;

    /**Configure the main internal regulator output voltage
    */
    __HAL_RCC_PWR_CLK_ENABLE();

    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /**Initializes the CPU, AHB and APB busses clocks
    */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.LSEState = RCC_LSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 8;
    RCC_OscInitStruct.PLL.PLLN = 96;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV6;
    RCC_OscInitStruct.PLL.PLLQ = 4;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        _Error_Handler(__FILE__, __LINE__);
    }

    /**Initializes the CPU, AHB and APB busses clocks
    */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;															//the SYSCLK is 32Mhz

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
    {
        _Error_Handler(__FILE__, __LINE__);
    }

    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
    PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
        _Error_Handler(__FILE__, __LINE__);
    }

    /**Configure the Systick interrupt time
    */
    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick
    */
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

    /* SysTick_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
void _Error_Handler(char * file, int line)
{
    /* USER CODE BEGIN Error_Handler_Debug */
    /* User can add his own implementation to report the HAL error return state */
    while(1)
    {
    }
    /* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
    /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    /* USER CODE END 6 */

}

#endif

/**
  * @}
  */

/**
  * @}
*/

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
